﻿using System;
using System.Collections.Generic;
using Microsoft.SharePoint;
using MS.InformationManagement.DAL.DocumentCenter;
using System.Linq;
using Microsoft.SharePoint.Linq;
using System.Text;
using System.IO;
using MS.InformationManagement.Support;
using MS.InformationManagement.Support.Constants;

namespace MS.InformationManagement.BLL.DocumentScheduler
{
    public class DocumentSchedulerBLL
    {
        /// <summary>
        /// Gets a collection of documents that have not been scheduled yet and that match the ids contained in the document ID array .
        /// </summary>
        /// <param name="documentIDArray">An array of integers containing the document IDs.</param>
        /// <param name="libraryGuid">The library which contains the document's GUID.</param>
        /// <returns></returns>
        public static IEnumerable<Radicado> GetDocuments(IEnumerable<int> documentIDArray, Guid libraryGuid)
        {
            SPList targetList = SPContext.Current.Web.Lists.GetList(libraryGuid, false);
            using (DCDocumentCenterDataContext ctx = new DCDocumentCenterDataContext(SPContext.Current.Web.Url))
            {
                //Microsoft.SharePoint.Taxonomy.TaxonomyFieldValue outboutType = TermStoreHelper.GetTaxonomyFieldByTerm(GlobalConstants.METADATA_GROUP_NAME
                //    , GlobalConstants.METADATA_TERM_TIPOS,
                //    GlobalConstants.METADATA_TERM_TIPO_RADICADO_SALIDA);
                EntityList<Radicado> entityList = ctx.GetList<Radicado>(targetList.Title);
                foreach (int id in documentIDArray)
                {
                    var obj = entityList.SingleOrDefault(r => r.Id.Equals(id) && r.FechaDeAgendado == null);
                    if (obj != null)
                        yield return obj;
                }
            }
        }

        /// <summary>
        /// Sets the schedule date for the given document.
        /// </summary>
        /// <param name="libraryGuid">The library which contains the document's GUID.</param>
        /// <param name="documentID">The document to be scheduled's ID.</param>
        /// <param name="scheduleDate">The document's schedule date.</param>
        public static void ScheduleDocument(Guid libraryGuid, int documentID, DateTime scheduleDate)
        {
            SPContext.Current.Web.AllowUnsafeUpdates = true;

            SPList targetList = SPContext.Current.Web.Lists.GetList(libraryGuid, false);
            SPListItem targetDoc = targetList.GetItemById(documentID);
            targetDoc[CustomSiteColumns.FIELD_DOCSET_FECHA_AGENDADO] = scheduleDate;
            targetDoc[CustomSiteColumns.FIELD_DOCUMENT_CATEGORY] = TermStoreHelper.GetTaxonomyFieldByTerm(GlobalConstants.METADATA_GROUP_NAME, GlobalConstants.METADATA_TERM_CATEGORY,
                GlobalConstants.METADATA_TERM_CATEGORY_AGENDADO);
            targetDoc.Update();

            SPContext.Current.Web.AllowUnsafeUpdates = false;
        }

        /// <summary>
        /// Gets a collection of scheduled documents, scheduled for the time interval between the given start date and the given end date.
        /// </summary>
        /// <param name="libraryGuid">The library which contains the documents's GUID.</param>
        /// <param name="startDate">The starting date for the schedule time interval.</param>
        /// <param name="endDate">The ending date for the schedule time interval.</param>
        /// <returns></returns>
        public static IEnumerable<MS.InformationManagement.DAL.DTOs.Radicado> GetScheduledDocuments(Guid libraryGuid, DateTime startDate, DateTime endDate)
        {
            SPList targetList = SPContext.Current.Web.Lists.GetList(libraryGuid, false);
            IEnumerable<MS.InformationManagement.DAL.DTOs.Radicado> foundDocuments = null;
            DCDocumentCenterDataContext ctx = null;

            try
            {
                ctx = new DCDocumentCenterDataContext(SPContext.Current.Web.Url);
                foundDocuments = GetScheduledDocumentsFromMyLibrary(libraryGuid, startDate, endDate, ref ctx)
                    .Union(GetScheduledDocumentsFromSharedLibrary(startDate, endDate, ref ctx));
            }
            catch (Exception) { throw; }
            finally { if (!ctx.Equals(default(DCDocumentCenterDataContext))) { ctx.Dispose(); } }
            
            return foundDocuments;
        }

        /// <summary>
        /// Unschedules a document on the given library.
        /// </summary>
        /// <param name="libraryGuid">The library which contains the document's GUID.</param>
        /// <param name="documentID">The document to be unscheduled's ID.</param>
        public static void UnscheduleDocument(string library, int documentID)
        {
            SPContext.Current.Web.AllowUnsafeUpdates = true;

            SPList targetList = SPContext.Current.Web.Lists.TryGetList(library);
            SPListItem targetDoc = targetList.GetItemById(documentID);
            targetDoc[CustomSiteColumns.FIELD_DOCSET_FECHA_AGENDADO] = null;
            targetDoc[CustomSiteColumns.FIELD_DOCUMENT_CATEGORY] = null;
            targetDoc.Update();

            SPContext.Current.Web.AllowUnsafeUpdates = false;
        }

        /// <summary>
        /// Gets the documents that require to be answered in the time interval between the given start date and the given end date
        /// </summary>
        /// <param name="libraryGuid">The library which contains the documents's GUID.</param>
        /// <param name="startDate">The starting date for the schedule time interval.</param>
        /// <param name="endDate">The ending date for the schedule time interval.</param>
        /// <returns></returns>
        public static IEnumerable<MS.InformationManagement.DAL.DTOs.Radicado> GetUnansweredDocuments(Guid libraryGuid, DateTime startDate, DateTime endDate)
        {
            SPList targetList = SPContext.Current.Web.Lists.GetList(libraryGuid, false);
            IEnumerable<MS.InformationManagement.DAL.DTOs.Radicado> foundDocuments = null;
            DCDocumentCenterDataContext ctx = null;
            
            try
            {
                ctx = new DCDocumentCenterDataContext(SPContext.Current.Web.Url);
                foundDocuments = GetUnansweredDocumentsFromSharedLibrary(startDate, endDate, ref ctx)
                    .Union(GetUnansweredDocumentsFroMyLibrary(libraryGuid, startDate, endDate, ref ctx));
            }
            catch (Exception) { throw; }
            finally { if (!ctx.Equals(default(DCDocumentCenterDataContext))) { ctx.Dispose(); } }

            return foundDocuments;
        }

        /// <summary>
        /// Determines whether [is any document scheduled] in [the specified selected ids] array.
        /// </summary>
        /// <param name="selectedIds">The selected items ids array</param>
        /// <param name="libraryGuid">The target library GUID.</param>
        /// <returns>
        ///   <c>true</c> if [is any document scheduled] in [the specified selected ids]; otherwise, <c>false</c>.
        /// </returns>
        public static bool IsAnyDocumentScheduled(int[] selectedIds, Guid libraryGuid)
        {

            SPList currentList = SPContext.Current.Web.Lists[libraryGuid];
            if (currentList.BaseTemplate.ToString() != GlobalConstants.GLOBAL_USER_LIBRARY_TEMPLATE)
                return false;

            SPQuery query = new SPQuery();
            query.Query = string.Format(@"
                            <Where>
                                <And>
                                    <In>
                                       <FieldRef Name='ID'/>
                                        <Values>
                                        {0}
                                        </Values> 
                                     </In>
                                     <IsNotNull>
                                        <FieldRef Name='ScheduleDate' />
                                     </IsNotNull>   
                                </And>
                               </Where> 
                            ", BuildIDFilters(selectedIds));
            SPListItemCollection result = currentList.GetItems(query);
            return result.Count > 0;
        }

        /// <summary>
        /// Builds the ID filters for the IsAnyDocumentScheduled InternalCaml.
        /// </summary>
        /// <param name="ids">The selected items id array</param>
        /// <returns></returns>
        private static string BuildIDFilters(int[] ids)
        {
            string filters = string.Empty;
            foreach (int i in ids)
            {
                filters += "<Value Type='Counter'>" + i + "</Value>";
            }
            return filters;
        }

        public static MS.InformationManagement.DAL.DTOs.Radicado GetRadicado(string library, int documentID)
        {
            //SPList targetList = SPContext.Current.Web.Lists.GetList(libraryGuid, false);
            MS.InformationManagement.DAL.DTOs.Radicado foundElement = null;
            using (DCDocumentCenterDataContext ctx = new DCDocumentCenterDataContext(SPContext.Current.Web.Url))
            {
                Radicado foundDocument = ctx.GetList<Radicado>(library).ScopeToFolder(string.Empty, true).SingleOrDefault(r => r.Id.Equals(documentID));
                foundElement = new DAL.DTOs.Radicado
                {
                    Name = foundDocument.NoRadicado,
                    FromTo = foundDocument.RemitenteDestinatario,
                    Subject = foundDocument.Asunto,
                    Keywords = foundDocument.Titulo
                };
            }
            return foundElement;
        }

        /// <summary>
        /// Gets the documents that require to be answered in the time interval between the given start date and the given end date,
        /// from the user's shared library (dependency library)
        /// </summary>
        /// <param name="startDate">The starting date for the schedule time interval.</param>
        /// <param name="endDate">The ending date for the schedule time interval.</param>
        /// <param name="context">The sharepoint linq data context.</param>
        /// <returns></returns>
        private static IEnumerable<MS.InformationManagement.DAL.DTOs.Radicado> GetUnansweredDocumentsFromSharedLibrary(DateTime startDate, DateTime endDate, ref DCDocumentCenterDataContext context)
        {
            IEnumerable<MS.InformationManagement.DAL.DTOs.Radicado> foundDocuments = null;
            string sharedLibrayName = PeopleHelper.GetPropertyCurrentUserProfile(GlobalConstants.UP_DEPARTMENT);
            EntityList<Radicado> entityList = context.GetList<Radicado>(sharedLibrayName);

            foundDocuments = (from r in entityList.ScopeToFolder(string.Empty, true)
                              where r.FechaRespuesta != null
                              && r.FechaRespuesta > startDate
                              && r.FechaRespuesta < endDate
                              && r.UsuarioAsignado.Equals(SPContext.Current.Web.CurrentUser.LoginName)
                              select new MS.InformationManagement.DAL.DTOs.Radicado
                              {
                                  ID = r.Id.Value,
                                  Name = r.Name,
                                  ScheduleDate = r.FechaDeAgendado,
                                  DueDate = r.FechaRespuesta,
                                  Library = sharedLibrayName
                              });


            return foundDocuments;
        }

        /// <summary>
        /// Gets the documents that require to be answered in the time interval between the given start date and the given end date,
        /// from the user's libeary
        /// </summary>
        /// <param name="libraryGuid">The library which contains the documents's GUID.</param>
        /// <param name="startDate">The starting date for the schedule time interval.</param>
        /// <param name="endDate">The ending date for the schedule time interval.</param>
        /// <param name="context">The sharepoint linq data context.</param>
        /// <returns></returns>
        private static IEnumerable<MS.InformationManagement.DAL.DTOs.Radicado> GetUnansweredDocumentsFroMyLibrary(Guid libraryGuid, DateTime startDate, DateTime endDate, ref DCDocumentCenterDataContext context)
        {
            SPList targetList = SPContext.Current.Web.Lists.GetList(libraryGuid, false);
            IEnumerable<MS.InformationManagement.DAL.DTOs.Radicado> foundDocuments = null;
            EntityList<Radicado> entityList = context.GetList<Radicado>(targetList.Title);

            foundDocuments = (from r in entityList
                              where r.FechaRespuesta != null
                              && r.FechaRespuesta > startDate
                              && r.FechaRespuesta < endDate
                              select new MS.InformationManagement.DAL.DTOs.Radicado
                              {
                                  ID = r.Id.Value,
                                  Name = r.Name,
                                  ScheduleDate = r.FechaDeAgendado,
                                  DueDate = r.FechaRespuesta,
                                  Library = targetList.Title
                              });

            return foundDocuments;
        }

        /// <summary>
        /// Gets a collection of scheduled documents, scheduled for the time interval between the given start date and the given end date,
        /// from the user's library
        /// </summary>
        /// <param name="libraryGuid">The library which contains the documents's GUID.</param>
        /// <param name="startDate">The starting date for the schedule time interval.</param>
        /// <param name="endDate">The ending date for the schedule time interval.</param>
        /// <param name="context">The sharepoint linq data context</param>
        /// <returns></returns>
        private static IEnumerable<MS.InformationManagement.DAL.DTOs.Radicado> GetScheduledDocumentsFromMyLibrary(Guid libraryGuid, DateTime startDate, DateTime endDate, ref DCDocumentCenterDataContext context)
        {
            SPList targetList = SPContext.Current.Web.Lists.GetList(libraryGuid, false);
            IEnumerable<MS.InformationManagement.DAL.DTOs.Radicado> foundDocuments = null;

            EntityList<Radicado> entityList = context.GetList<Radicado>(targetList.Title);
            foundDocuments = (from r in entityList
                              where r.FechaDeAgendado != null
                              && r.FechaDeAgendado >= startDate
                              && r.FechaDeAgendado <= endDate
                              select new MS.InformationManagement.DAL.DTOs.Radicado
                              {
                                  ID = r.Id.Value,
                                  Name = r.Name,
                                  ScheduleDate = r.FechaDeAgendado,
                                  DueDate = r.FechaRespuesta,
                                  Library = targetList.Title
                              });

            return foundDocuments;
        }

        /// <summary>
        /// Gets a collection of scheduled documents, scheduled for the time interval between the given start date and the given end date,
        /// from the user's shared library (dependency library)
        /// </summary>
        /// <param name="startDate">The starting date for the schedule time interval.</param>
        /// <param name="endDate">The ending date for the schedule time interval.</param>
        /// <param name="context">The sharepoint linq data context</param>
        /// <returns></returns>
        private static IEnumerable<MS.InformationManagement.DAL.DTOs.Radicado> GetScheduledDocumentsFromSharedLibrary(DateTime startDate, DateTime endDate, ref DCDocumentCenterDataContext context)
        {
            IEnumerable<MS.InformationManagement.DAL.DTOs.Radicado> foundDocuments = null;
            string sharedLibrayName = PeopleHelper.GetPropertyCurrentUserProfile(GlobalConstants.UP_DEPARTMENT);
            EntityList<Radicado> entityList = context.GetList<Radicado>(sharedLibrayName);

            foundDocuments = (from r in entityList.ScopeToFolder(string.Empty, true)
                              where r.FechaDeAgendado != null
                              && r.FechaDeAgendado >= startDate
                              && r.FechaDeAgendado <= endDate
                              && r.UsuarioAsignado.Equals(SPContext.Current.Web.CurrentUser.LoginName)
                              select new MS.InformationManagement.DAL.DTOs.Radicado
                              {
                                  ID = r.Id.Value,
                                  Name = r.Name,
                                  ScheduleDate = r.FechaDeAgendado,
                                  DueDate = r.FechaRespuesta,
                                  Library = sharedLibrayName
                              });

            return foundDocuments;
        }
    }
}
